package problem.year2021.february;

/**
 * 给定一个正整数数组 A，如果 A 的某个子数组中不同整数的个数恰好为 K，则称 A 的这个连续、不一定独立的子数组为好子数组。
 * <p>
 * （例如，[1,2,3,1,2] 中有 3 个不同的整数：1，2，以及 3。）
 * <p>
 * 返回 A 中好子数组的数目。
 * <p>
 * 示例 1：
 * <p>
 * 输入：A = [1,2,1,2,3], K = 2
 * 输出：7
 * 解释：恰好由 2 个不同整数组成的子数组：[1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2].
 * <p>
 * 示例 2：
 * <p>
 * 输入：A = [1,2,1,3,4], K = 3
 * 输出：3
 * 解释：恰好由 3 个不同整数组成的子数组：[1,2,1,3], [2,1,3], [1,3,4].
 * <p>
 * 提示：
 * <p>
 * 1 <= A.length <= 20000
 * 1 <= A[i] <= A.length
 * 1 <= K <= A.length
 */
public class February9 {
    public int subarraysWithKDistinct(int[] A, int K) {
        // 因为 1 <= A[i] <= A.length，所以A[i]中的数字是从0到A.length之间的
        // 设置一个数组用来记录每个数字出现的次数
        int[] nums = new int[A.length];
        // 设置一个左右指针left 和 right
        int left = 0, right = 0;
        // 设置一个值，记录当前子字符串中不同整数个数
        int p = 0, res = 0;
        while (left <= right) {
            // 先确定右指针是否到边界了
            if (right < A.length){
                // 先确定指针向那边走
                if (p <= K) {
                    if (nums[right] == 0){
                        p++;
                        nums[right]++;
                    } else {
                        nums[right]++;
                    }
                    // 右指针移动
                    right++;
                } else {
                    res++;
                    if (nums[left] == 1){
                        p--;
                        nums[left]--;
                    } else {
                        nums[left]--;
                    }
                    // 左指针移动
                    left++;
                }
            } else {
                if (p >= K){
                    res++;
                    if (nums[left] == 1){
                        p--;
                        nums[left]--;
                        left++;
                    } else {
                        nums[left]--;
                        left++;
                    }
                } else {
                    break;
                }
            }

        }
        // 利用hash特性来
        return res;
    }
}
